#pragma once 

#include <system_error>
#include <memory>
#include "helper/transaction/ITransaction.h"


namespace helper {
namespace transaction {

class Transaction : public ITransaction {
  enum Status {
    INITED = 0,
    STARTED,
    COMMITTED,
    ROLLBACKED,
  };

public:
  Transaction();
  ~Transaction();

  std::error_code begin() override;
  std::error_code commit() override;
  std::error_code rollback() override;

protected:
  virtual std::error_code _begin() ;
  virtual std::error_code _commit()  ;
  virtual std::error_code _rollback() ;


public:
  inline bool isInited() const {
    return _status == INITED;
  }
  inline bool isStarted() const {
    return _status == STARTED;
  }
  inline bool isRollbacked() const {
    return _status == ROLLBACKED;
  }
  inline bool isCommitted() const {
    return _status == COMMITTED;
  }

private:
  Status _status;
};

class ScopeTransaction {
public:
  
  ScopeTransaction(std::unique_ptr<ITransaction> && trans) 
  :_trans(std::move(trans))
  {
    _trans->begin();
  }
  ~ScopeTransaction()
  {
    _trans->commit();
  }

  ScopeTransaction(const ScopeTransaction & ) = delete;
  ScopeTransaction& operator= (const ScopeTransaction & ) = delete;

  ScopeTransaction(ScopeTransaction &&) = delete;
  ScopeTransaction& operator= (ScopeTransaction && ) = delete;

  std::error_code rollback(){
    return _trans->rollback();
  }

private:
  std::unique_ptr<ITransaction> _trans;
};

}//namespace transaction
}//namespace helper
